home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------- */
- /* This DES software was developed by Steve Kent and John Linn */
- /* of BBN Communications Corporation, Cambridge, MA */
- /* Do not redistribute this software, or integrate with other */
- /* software, without preserving this notice */
- /* ----------------------------------------------------------------- */
-
- /* ksb.c -- John Linn, 21 April 1983 --
- This program uses an optimized, table-driven method to compute a
- DES key schedule from 8 input bytes.
- Once the optimizing table (pc2otab) has been computed, generation
- of a schedule takes approximately 12 user ms on a C/70.
-
- Note: there is still room to optimize pc1 and tweak out a couple
- of extra milliseconds from the key schedule build, but this
- should only be important if and when adaptation to an environment
- which needs to dynamically change keys is considered.
-
- 21 Apr. -- removed c30 special case. c30 now takes same key format,
- and output is always to file 'ks'.
-
- 6 May -- added command line option to specify name of output file.
- if no command arg, output is still to 'ks'.
-
- */
-
- #include <stdio.h>
-
- /* tables to describe permutations, per NBS FIPS */
-
- static int pc1c [] =
- { 57, 49, 41, 33, 25, 17, 9,
- 1, 58, 50, 42, 34, 26, 18,
- 10, 2, 59, 51, 43, 35, 27,
- 19, 11, 3, 60, 52, 44, 36 };
-
- static int pc1d [] =
- { 63, 55, 47, 39, 31, 23, 15,
- 7, 62, 54, 46, 38, 30, 22,
- 14, 6, 61, 53, 45, 37, 29,
- 21, 13, 5, 28, 20, 12, 4 };
-
- static int shiftsked []=
- { 1, 1, 2, 2, 2, 2, 2, 2,
- 1, 2, 2, 2, 2, 2, 2, 1 };
-
- static int pc2 [] =
- { 14, 17, 11, 24, 1, 5,
- 3, 28, 15, 6, 21, 10,
- 23, 19, 12, 4, 26, 8,
- 16, 7, 27, 20, 13, 2,
- 41, 52, 31, 37, 47, 55,
- 30, 40, 51, 45, 33, 48,
- 44, 49, 39, 56, 34, 53,
- 46, 42, 50, 36, 29, 32 };
-
- /* --- some bit manipulation primitives --- */
-
- /* g_keybit -- extract bit bnum from the key in inkey */
- #define g_keybit(bnum) (01 & (inkey [bnum/8] >> (8 - (bnum%8))))
-
- long lrot28 (lval)
- /* do left rotate of 28 bit quantity */
- long lval;
- {
- lval <<= 1;
- if (0X10000000L & lval) lval++;
- lval &= 0XFFFFFFFL;
- return (lval);
- }
-
- /* --- following code and data does key schedule generation --- */
-
- unsigned skedkeys [16] [4];
-
- unsigned inkey [8]; /* input key goes here */
-
- long pc2otab [8] [128]; /* table to optimize pc2 */
-
- spc2otab () /* initialize pc2otab for pc2 lookups */
- {
- #define NOTSEL -1
-
- extern long pc2otab [8] [128];
- extern int pc2 [48];
-
- int bn, bv, bitloc, i;
- int bitindx [7];
-
- for (bn = 0; bn < 8; bn++) /* each input 7-bit byte, l->r */
- {
- for (i = 0; i < 7; i++) /* find each bit in the byte */
- {
- /* determine where (or if) pc2 places the given bit in the
- output. set bitindx [0] to the bit number (1->48,l->r)
- where the MSB of the byte occurs, or to NOTSEL if pc2
- doesn't pick it. similar down through bitindx [6]. */
-
- for (bitloc = 0; bitloc < 48; bitloc++)
- {
- /* trying until a match in pc2 found or table exhausted */
- if (pc2 [bitloc] == (1 + ((bn * 7) + i)))
- {
- bitindx [i] = bitloc + 1;
- break;
- }
- }
- if (bitloc == 48) bitindx [i] = NOTSEL;
- }
-
- for (bv = 0; bv < 128; bv++)
- {
- /* setting up a table entry for each input byte value */
- pc2otab [bn] [bv] = 0L;
- if (bn < 4) /* this is left word (nbs bits 1-24) */
- {
- for (i = 0; i < 7; i++)
- {
- if (NOTSEL == bitindx [i]) continue;
- if (bv & (01 << (6 - i)))
- pc2otab [bn] [bv] |= (0X1L << (24 - bitindx [i]));
- }
- }
- else /* this is right word (nbs bits 25-48) */
- {
- for (i = 0; i < 7; i++)
- {
- if (NOTSEL == bitindx [i]) continue;
- if (bv & (01 << (6 - i)))
- pc2otab [bn] [bv] |= (0X1L << (48 - bitindx [i]));
- }
- }
- }
- }
- }
-
- ksmake () /* Make a key schedule from key bytes in inkey */
- {
- extern unsigned skedkeys [16] [4];
- extern long pc2otab [8] [128];
-
- int round;
- long pcct, pcdt;
- long pc2out [2];
- int i;
-
- /* do pc-1 permutation, extracting bits from inkey */
- pcct = pcdt = 0L;
- for (i = 0; i < 27; i++)
- /* filling all appropriate bits */
- {
- pcct |= g_keybit(pc1c [i]);
- pcdt |= g_keybit(pc1d [i]);
- pcct <<= 1;
- pcdt <<= 1;
- }
- /* one final ior, without a shift */
- pcct |= g_keybit(pc1c [i]);
- pcdt |= g_keybit(pc1d [i]);
-
- for (round = 0; round < 16; round++)
- {
- /* always at least one shift */
- pcct = lrot28 (pcct);
- pcdt = lrot28 (pcdt);
-
- if (shiftsked [round] == 2)
- { /* this round needs another shift */
- pcct = lrot28 (pcct);
- pcdt = lrot28 (pcdt);
- }
-
- /* Now, pcct and pcdt have the values on which we can apply
- pc2 and select the key bits, storing them in pc2out[0] and
- pc2out[1]. The high order [pc2out[0]] bits all come from
- pcct, and the low order from pcdt. */
-
- pc2out [0] = pc2otab [0] [pcct >> 21];
- pc2out [0] |= pc2otab [1] [0X7F & (pcct >> 14)];
- pc2out [0] |= pc2otab [2] [0X7F & (pcct >> 7)];
- pc2out [0] |= pc2otab [3] [0X7F & pcct];
-
- pc2out [1] = pc2otab [4] [pcdt >> 21];
- pc2out [1] |= pc2otab [5] [0X7F & (pcdt >> 14)];
- pc2out [1] |= pc2otab [6] [0X7F & (pcdt >> 7)];
- pc2out [1] |= pc2otab [7] [0X7F & pcdt];
-
- /* order key bits and bytes so as to be compatible with
- the format generated by the E implementation */
-
- skedkeys [round] [0] = 0XFC00 & (pc2out [0] >> 8);
- skedkeys [round] [0] |= (0XFC & (pc2out [0] >> 4));
- skedkeys [round] [1] = 0XFC00 & (pc2out [1] >> 8);
- skedkeys [round] [1] |= (0XFC & (pc2out [1] >> 4));
-
- skedkeys [round] [2] = 0XFC00 & (pc2out [0] >> 2);
- skedkeys [round] [2] |= (0XFC & (pc2out [0] << 2));
- skedkeys [round] [3] = 0XFC00 & (pc2out [1] >> 2);
- skedkeys [round] [3] |= (0XFC & (pc2out [1] << 2));
- }
- }
-
- int parval () /* test parity of key in inkey; return 1 iff OK */
- {
- int i, j;
- int parac;
- unsigned incopy;
-
- for (i = 0; i < 8; i++) /* do each byte */
- {
- parac = 0;
- incopy = inkey [i];
-
- for (j = 0; j < 8; j++) /* 8 bits in a DES byte */
- {
- if (incopy & 01) parac++;
- incopy >>= 1;
- }
- if (! (parac & 01)) return (0); /* no odd parity on this byte */
- }
- return (1); /* OK on all of them */
- }
-
- /* main for ksb -- accept and validate key, output schedule */
- main (argc, argv)
- int argc;
- char *argv [];
- {
- extern unsigned skedkeys [16] [4];
- extern unsigned inkey [8];
-
- int i, j;
- FILE * fp, *fopen ();
-
- spc2otab (); /* compute internal table */
-
- printf ("Enter DES key as 8 hex bytes: ");
- scanf ("%x %x %x %x %x %x %x %x",
- &inkey [0], &inkey [1], &inkey [2], &inkey [3],
- &inkey [4], &inkey [5], &inkey [6], &inkey [7]);
-
- if (! parval ())
- {
- printf ("Bad parity on key... aborting...\n");
- exit (1);
- }
-
- ksmake ();
-
-
- if (NULL == (fp = fopen (((argc > 1) ? argv [1] : "ks"), "w")))
- {
- printf ("ksb -- can't open output file '%s'\n",
- ((argc > 1) ? argv [1] : "ks"));
- exit (1);
- }
-
- for (i = 0; i < 16; i++) /* output entire schedule to file */
- {
- for (j = 0; j < 4; j++)
- /* format is xxxxxx00xxxxxx00 */
- fprintf (fp, "%x\n", skedkeys [i] [j]);
- }
-
- printf ("ksb -- key schedule output to file '%s'\n",
- ((argc > 1) ? argv [1] : "ks"));
- }
-
-